<?php

namespace app\api\service\shop;

use app\admin\model\template\Order;
use app\admin\model\template\OrderCommissionRecord;
use app\admin\model\template\Template;
use app\admin\model\User;
use think\Db;
use think\Exception;
use think\exception\PDOException;

/**
 * 订单服务类
 */
class OrderService
{

    /**
     * 获取订单信息
     * @param int $userId 用户ID
     * @param int $companyId 公司ID
     * @param bool $type 是否是公司访问
     * @param string $orderId 订单编号
     */
    public function getOrderInfo(int $userId, int $companyId, bool $type, string $orderId)
    {
        $where = ['user_id' => $userId, 'order_sn' => $orderId, 'company_id' => null];
        if ($type) $where['company_id'] = $companyId;
        $order = Order::where($where)->field(['*', 'type type_id', 'pay_state pay_type'])->find();
        if (is_null($order)) return null;
        $order->appendRelationAttr('user', ['nickname', 'avatar']);
        $order->appendRelationAttr('template', ['name', 'sn']);
        $order['endTime'] = $order->getEndTime($order->pay_type, $order->getData('createtime'));
        if (is_null($order->company_id)) $order->pay_mode = '个人数据能量';
        else $order->pay_mode = '团队数据能量';
        return $order;
    }

    /**
     * 获取订单信息列表
     * @param int $userId 用户ID
     * @param int $companyId 公司ID
     * @param bool $type 是否是公司访问
     * @param int $page 页码
     * @param int $limit 每页展示数据
     * @param int $resource 订单支付状态, 0 - 待付、1 - 已付、2 - 已取消、3 - 查询全部
     */
    public function getOrderInfoList(int $userId, int $companyId, bool $type, int $page, int $limit, int $resource = 3)
    {
        $where = ['user_id' => $userId, 'company_id' => null];
        if ($type) $where['company_id'] = $companyId;

        // 构建订单支付状态条件
        if ($resource != 3) $where['pay_state'] = $resource;

        $data = Order::where($where)
            ->field(['id', 'order_sn', 'template_id', 'price', 'pay_state', 'createtime', 'type', 'type type_id', 'pay_state pay_type', 'carbon_account_price', 'factors'])
            ->order('createtime desc')
            ->paginate($limit)
            ->each(function ($order) {
                $order['endTime'] = $order->getEndTime($order->pay_type, $order->getData('createtime'));
                $order->appendRelationAttr('template', ['name']);
            });
        return ['total' => $data->total(), 'row' => $data->items()];
    }

    /**
     * 取消订单
     * @param int $userId 用户ID
     * @param int $companyId 公司ID
     * @param bool $type 是否是公司登录
     * @param string $orderId 订单编号
     */
    public function cancelOrder(int $userId, int $companyId, bool $type, string $orderId)
    {
        $where = ['user_id' => $userId, 'order_sn' => $orderId, 'company_id' => null];
        if ($type) $where['company_id'] = $companyId;
        $order = Order::where($where)->value('pay_state');
        if (is_null($order)) return '当前订单不存在';
        switch ($order) {
            case 1:
                return '当前订单已支付';
            case 2:
                return '当前订单已取消';
        }
        $where = array_merge($where, ['pay_state' => 0]);
        $data = Order::where($where)->update(['pay_state' => 2, 'updatetime' => time()]);
        if ($data) return null;
        return '订单取消失败';
    }

    /**
     * 支付订单
     * @param int $userId 用户ID
     * @param int $qdUserId 青牒用户ID
     * @param int $companyId 公司ID
     * @param bool $type 是否是公司访问
     * @param string $orderId 订单编号
     */
    public function buyOrder(int $userId, int $qdUserId, int $companyId, bool $type, string $orderId)
    {
        // 构建访问条件
        $where = ['user_id' => $userId, 'order_sn' => $orderId];

        // 获取模板价格
        $order = Order::where($where)->find();
        if (is_null($order)) return '当前订单不存在';
        switch ($order) {
            case $order->getData('pay_state') == 1:
                return '订单已支付';
            case $order->getData('pay_state') == 2:
                return '订单已取消';
        }
        $price = $order->price;
        // 连接青碟
        $qd = Db::connect(config('database.qd'));
        // 获取用户的积分
        if (!$type) $qdUser = $qd->table('fa_user')->where('id', $userId)->field(['score', 'money'])->find();
        else $qdUser = $qd->table('fa_department')->where('id', $companyId)->field(['score', 'money'])->find();
        if (is_null($qdUser)) return '获取青碟数据失败';
        $score = $qdUser['score'];
        $money = $qdUser['money'];
        if ($score < $price) return '当前数据能量不足, 请获取数据能量';
        // 获取作者信息
        $orderRecord = OrderCommissionRecord::where(['type' => 1, 'order_id' => $order->id])->find();
        if (is_null($orderRecord)) return '服务错误';
        $authorCompanyId = $orderRecord->company_id;
        $authorId = $orderRecord->author_id;
        if ($authorCompanyId == 0) $authorType = false;
        else $authorType = true;
        // 开启事务
        $qd->startTrans();
        Db::startTrans();
        try {
            // 扣费和记录日志
            $time = time();
            $num = Db::name('order')->where($where)->update(['pay_state' => 1, 'paytime' => $time, 'updatetime' => $time]);
            if (!$num) throw new Exception('当前未支付的该订单不存在');
            // 扣除数据能量
            decCosts($qd, $price, $qdUserId, $companyId, $score, '碳足迹', '购买核算模板', $type);
            // 作者抽成
            incCosts($qd, $order->author_commission_ratio, $authorId, $authorCompanyId, $money, '碳足迹', '模板出售', $authorType);
            // 其他抽成
//            $this->dataDepositoryFee();
//            $this->informationServiceFee();
//            $this->agencyAccountFee();
//            $this->platformServiceFee();
            // 增加销量
            $num = Db::name('template')->where('id', $order->template_id)->setInc('sales');
            if (!$num) throw new  Exception('服务错误');
            $qd->commit();
            Db::commit();
        } catch (PDOException $e) {
            $qd->rollback();
            Db::rollback();
            return '服务错误';
        } catch (Exception $e) {
            $qd->rollback();
            Db::rollback();
            return $e->getMessage();
        }
        return null;
    }

    /**
     * 数据存证费用
     */
    public function dataDepositoryFee()
    {

    }

    /**
     * 信息服务费用
     */
    public function informationServiceFee()
    {

    }

    /**
     * 核算费用
     */
    public function agencyAccountFee()
    {

    }

    /**
     * 平台服务费用
     */
    public function platformServiceFee()
    {

    }

    /**
     * 创建订单
     * @param int $id 模板ID
     * @param int $userId 用户ID
     * @param int $company_Id 公司ID
     * @param bool $type 是否是公司访问
     * @param string $orderId 订单编号
     */
    public function createOrder(int $id, int $userId, int $company_Id, bool $type, string $orderId)
    {
        $template = Template::where('id', $id)->find();
        if (is_null($template)) return '当前模板不存在';
        $price = $template->price;
        if ($template->user_id == $userId)
            return '请勿购买自己的模板';
        $insert = [];
        if ($type) $insert = ['company_id' => $company_Id];
        $orders = Order::where('user_id', $userId)->where('template_id', $id)->where('pay_state', '<>', 2)->field(['order_sn', 'pay_state'])->select();
        if (!$orders->isEmpty()) {
            foreach ($orders as $order) {
                if ($order->getData('pay_state') == 1) return '当前订单已购买';
                else  return ['message' => '当前待支付订单已存在', 'sn' => $order->order_sn];
            }
        }
//        $author = User::where('id', $template->user_id)->field(['id user_id', 'company_id'])->find();
//        if (is_null($author)) return '当前产品不存在或已被删除';
        Db::startTrans();
        try {
            // 获取抽成费用
            $result = $this->getExtractFee($price);
            $moneyList = [];
            $proportionList = [];
            foreach ($result as $key => $item) {
                $moneyList[$key] = $item['money'];
                $proportionList[$key] = $item['proportion'];
            }
            $time = time();
            // 构建插入字段
            $insert = array_merge($insert, ['order_sn' => $orderId, 'user_id' => $userId, 'template_id' => $id, 'pay_state' => 0, 'type' => 1, 'price' => $price, 'createtime' => $time], $moneyList);
            $num = Order::insertGetId($insert);
            if (!$num) throw new Exception('创建订单失败');
            // 作者抽成
            $authorCompanyId = $template->company_id;
            $authorId = $template->user_id;
            if (is_null($authorCompanyId)) $authorType = false;
            else $authorType = true;
            $this->extractRecord($moneyList, $proportionList, $num, $authorId, $authorCompanyId, $authorType, $time);
            Db::commit();
        } catch (PDOException|Exception $e) {
            Db::rollback();
            throw $e;
            return $e->getMessage();
        }
        return null;
    }

    /**
     * 获取各级抽成费用
     * @param int $money 支付费用
     */
    public function getExtractFee(int $money)
    {
        $result = Db::name('commission_config')->column('key, value');
        if (is_null($result)) throw new Exception('请联系管理员设置抽成比例');
        $sum = 0;
        foreach ($result as $key => $value) {
            $fee = round(bcmul($money ,$value,3),2);
            $sum += $fee;
            $result[$key] = ['proportion' => $value, 'money' => $fee];
        }
        $result['platform_service_fee']['money'] += round(bcsub($money , $sum,3),2);
        return $result;
    }

    /**
     * 抽成记录
     * @param array $money 费用列表
     * @param array $ratio 占比列表
     * @param int $orderId 订单ID
     * @param int $userId 作者ID
     * @param int $companyId 公司ID
     * @param int $type 是否是公司
     * @param int $time 支付时间
     */
    public function extractRecord(array $money, array $ratio, int $orderId, int $userId, int $companyId, int $type, int $time)
    {
        $insert = [
            ['type' => 1, 'author_id' => $userId, 'order_id' => $orderId, 'fee' => $money['author_commission_ratio'], 'ratio' => $ratio['author_commission_ratio'], 'company_id' => $type ? $companyId : 0, 'createtime' => $time],
            ['type' => 2, 'author_id' => 0, 'order_id' => $orderId, 'fee' => $money['information_service_fee'], 'ratio' => $ratio['information_service_fee'], 'company_id' => 0, 'createtime' => $time],
            ['type' => 3, 'author_id' => 0, 'order_id' => $orderId, 'fee' => $money['platform_service_fee'], 'ratio' => $ratio['platform_service_fee'], 'company_id' => 0, 'createtime' => $time],
            ['type' => 4, 'author_id' => 0, 'order_id' => $orderId, 'fee' => $money['data_depository_fee'], 'ratio' => $ratio['data_depository_fee'], 'company_id' => 0, 'createtime' => $time],
            ['type' => 5, 'author_id' => 0, 'order_id' => $orderId, 'fee' => $money['agency_account_fee'], 'ratio' => $ratio['agency_account_fee'], 'company_id' => 0, 'createtime' => $time],
        ];
        $result = Db::name('order_commission_record')->insertAll($insert);
        if ($result != 5) throw new Exception('数据库错误');
    }

    /**
     * 获取订单价格
     * @param string $orderId 订单编号
     * @param int $userId 用户ID
     * @param int $companyId 公司ID
     * @param bool $type 是否是公司访问
     */
    public function getOrderMoney(string $orderId, int $userId, int $companyId, bool $type)
    {
        $where = ['order_sn' => $orderId, 'user_id' => $userId];
        if ($type) $where['company_id'] = $companyId;
        return Order::where($where)->value('price');
    }

    /**
     * 设置订单过期
     */
    public function setOrderExpire()
    {
        $time = time();
        return Order::where('pay_state', 0)
            ->where('createtime', '<=', $time - 900)
            ->update(['updatetime' => $time, 'pay_state' => 2]);
    }

    /**
     * 获取出售的订单信息列表
     * @param int $userId 用户ID或公司ID
     * @param bool $type 是否是公司访问
     * @param int $page 页码
     * @param int $limit 每页展示数据
     * @param int $resource 订单支付状态, 0 - 待付、1 - 已付、2 - 已取消、3 - 查询全部
     */
    public function getSellOrderInfoList(int $userId, bool $type, int $page, int $limit, int $resource = 3)
    {
        $fWhere = ['from_user' => $userId];
        $rWhere = ['r.author_id' => $userId];

        // 构建订单支付状态条件
        if ($resource != 3) {
            $fWhere['o.pay_state'] = $resource;
            $rWhere['o.pay_state'] = $resource;
        }

        $data = Db::name('order_factor')
            ->alias('f')
            ->join('zt_order o', 'o.id = f.order_id')
            ->where($fWhere)
            ->fieldRaw('distinct order_id, o.order_sn, o.price, o.createtime, o.template_id, o.pay_state, 0 fee, 2 type')
            ->union(function ($query) use ($rWhere) {
                $query->table('zt_order_commission_record')
                    ->alias('r')
                    ->join('zt_order o', 'o.id = r.order_id')
                    ->where($rWhere)
                    ->fieldRaw('r.order_id, o.order_sn, o.price, o.createtime, o.template_id, o.pay_state ,r.fee fee, 1 type');
            })
            ->union(function ($query) use ($fWhere) {
                $query->table('zt_order_template')
                    ->alias('t')
                    ->join('zt_order o', 'o.id = t.order_id')
                    ->where($fWhere)
                    ->fieldRaw('distinct t.order_id, o.order_sn, t.price, o.createtime, o.template_id, o.pay_state ,t.commission fee, 3 type');
            })
            ->order('createtime', 'desc')
            ->page($page, $limit)
            ->select();
        return $data->each(function ($item) use ($userId) {
            $data = [0 => '待付款', 1 => '已完成', 2 => '已取消'];
            $item['pay_state_name'] = $data[$item['pay_state']];
            $item['endTime'] = $item['pay_state'] == 0 ? $item['createtime'] + 900 : null;
            if ($item['type'] == 1) {
                $item['name'] = Template::where('id', $item['template_id'])->value('name');
                $item['type_name'] = '核算模板';
            } else if ($item['type'] == 2) {
                $total = 0;
                $ids = Db::name('order_factor')
                    ->alias('f')
                    ->join('zt_carbon_factor c', 'c.id = f.factor_id')
                    ->where('f.order_id', $item['order_id'])
                    ->where('c.user_id', $userId)
                    ->field(['c.id', 'c.name', 'c.price', 'f.price fee'])
                    ->select()
                    ->each(function ($item) use (&$total) {
                        $item['type_name'] = '碳排放因子&数据库';
                        $total += $item['fee'];
                        unset($item['fee']);
                        return $item;
                    });
                $item['factors'] = $ids;
                $item['fee'] = $total;
                unset($item['order_id'], $item['id'], $item['price']);
            } else {
                $actual = 0;
                $template = Db::name('order_template')->where('from_user', $userId)->where('order_id', $item['order_id'])
                    ->field(['template_id', 'price', 'commission'])
                    ->select()
                    ->each(function ($item) use (&$actual) {
                        $item['name'] = Template::where('id', $item['template_id'])->value('name');
                        $item['type_name'] = '核算模板分成';
                        $actual += $item['commission'];
                        return $item;
                    });
                $item['data'] = $template;
                $item['type_name'] = '核算模板分成';
                $item['fee'] = $actual;
            }
            unset($item['pay_state']);
            return $item;
        });
    }

    /**
     * 获取出售的订单信息
     * @param int $userId 用户ID
     * @param int $type 订单类型, 1 -> 模板、2 -> 因子、3 -> 分成
     * @param string $orderId 订单编号
     */
    public function getSellOrderInfo(int $userId, int $type, string $orderId)
    {
        $order = Order::where('order_sn', $orderId)->field(['id', 'user_id', 'order_sn', 'template_id', 'price', 'pay_state', 'type', 'createtime', 'type type_id', 'pay_state pay_type', 'paytime'])->find();
        if (is_null($order)) return null;
        if ($type == 1) {
            $bool = true;
            $actual = 0;
            $service = 0;
            OrderCommissionRecord::where('order_id', $order->id)
                ->select()
                ->each(function ($item) use (&$bool, &$actual, &$service, $userId) {
                    if ($item->type == 1) {
                        $actual = $item->fee;
                        $bool = $item->author_id != $userId;
                    } else {
                        $service += $item->fee;
                    }
                });
            if ($bool) return null;
        } else if ($type == 2) {
            $actual = 0;
            $service = 0;
            $ids = Db::name('order_factor')
                ->alias('f')
                ->join('zt_carbon_factor c', 'c.id = f.factor_id')
                ->where('f.order_id', $order['id'])
                ->where('c.user_id', $userId)
                ->field(['c.id', 'c.name', 'c.price', 'f.price fee', 'platform_service_fee service_fee', 'c.sn'])
                ->select()
                ->each(function ($item) use (&$actual, &$service) {
                    $item['type_name'] = '碳排放因子&数据库';
                    $actual += $item['fee'];
                    $service += $item['service_fee'];
                    unset($item['fee'], $item['service_fee']);
                    return $item;
                });
            $order['factors'] = $ids;
        } else {
            $actual = 0; // 实收分成
            $service = 0; // 平台服务费
            $data = Db::name('order_template')->where('order_id', $order['id'])->where('from_user', $userId)->field(['template_id', 'price', 'service_fee', 'commission'])->select();
            if (is_null($data)) return null;
            $data = $data->each(function ($item) use (&$actual, &$service) {
                $actual += $item['commission']; // 每个模板的分成
                $service += $item['service_fee']; // 每个模板的平台服务费
                $item['type_name'] = '核算模板分成';
                $data = Template::where('id', $item['template_id'])->field(['id', 'name', 'sn'])->find();
                if (is_null($data)) return null;
                $item['name'] = $data['name'];
                $item['sn'] = $data['sn'];
                return $item;
            });
            $order->data = $data;
            $order['type_id'] = 3;
        }
        $order['actual'] = $actual;
        $order['service'] = $service;
        $order->appendRelationAttr('user', ['nickname', 'avatar']);
        $order->appendRelationAttr('template', ['name', 'sn']);
        $order['endTime'] = $order->getEndTime($order->pay_type, $order->getData('createtime'));

        if ($order->pay_state == 1) $order->pay_mode = '团队数据能量';
        unset($order['user_id']);
        return $order;
    }

}